<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      function Promise(callback) {
        /**
         * pending   等待
         * fulfilled 完成
         * rejected  错误
         * **/
        this.state = 'pending';
        this.thens = [];
        this.catchs = [];
        this.thenValue = undefined;
        this.catchValue = undefined;

        if (!callback || typeof callback !== 'function') {
          throw new Error('Promise callback is not function');
        }
        try {
          callback(this.resolve.bind(this), this.reject.bind(this));
        } catch (error) {
          this.reject(error);
        }
      }

      Promise.prototype.resolve = function (value) {
        if (this.state === 'pending') {
          this.state = 'fulfilled';
          this.thenValue = value;
          setTimeout(() => {
            if (this.thens.length) {
              this.thens.shift()(value);
            }
          });
        }
      };

      Promise.prototype.reject = function (e) {
        if (this.state === 'pending') {
          this.state = 'rejected';
          this.catchValue = e;
          setTimeout(() => {
            if (this.catchs.length) {
              this.catchs.shift()(e);
            } else {
              throw new Error(e);
            }
          });
        }
      };

      Promise.prototype.then = function (fulfilledCb, rejectedCb) {
        fulfilledCb =
          typeof fulfilledCb === 'function' ? fulfilledCb : (val) => val;
        rejectedCb =
          typeof rejectedCb === 'function'
            ? rejectedCb
            : (e) => {
                throw new Error(e);
              };
        return new Promise((reslove, reject) => {
          if (this.state === 'pending') {
            this.thens.push((v) => {
              const data = fulfilledCb(v);
              if (data instanceof Promise) {
                data.then(reslove, reject);
              } else {
                reslove(data);
              }
            });
            this.catchs.push((v) => {
              const data = rejectedCb(v);
              if (data instanceof Promise) {
                data.then(reslove, reject);
              } else {
                reject(data);
              }
            });
          } else if (this.state === 'fulfilled') {
            const data = fulfilledCb(this.thenValue);
            if (data instanceof Promise) {
              data.then(reslove, reject);
            } else {
              reslove(data);
            }
            this.thens.push(() => {});
          } else {
            const data = rejectedCb(this.catchValue);
            this.catchs.push(() => {});
          }
        });
      };

      Promise.prototype.catch = function (rejectedCb) {
        return this.then(undefined, rejectedCb);
      };
      const p = new Promise((reslove, reject) => {
        /**
         * 1. 第一种情况,先触发了 reslove/reject,在触发了then/catch
         * 2. 第二种情况,先触发了 then/catch,后触发了reslove/reject
         * **/
        // setTimeout(() => {
        //   reslove(123);
        // }, 2000);
        // reject('error');
        // throw new Error('error');
        reslove(123);
      });
      p.then((ret) => {
        console.log(ret, '第一次');
        return ret + 1;
      }).then((ret) => {
        console.log(ret, '第二次');
      });
    </script>
  </body>
</html>
